#include <arpa/inet.h>
#include <sys/socket.h>
#include <pthread.h>
#include <signal.h>
#include "Gomoku.h"
#include "mouse_input.h"
#include <math.h>



#define socket_IP "192.168.13.154"
#define socket_PORT 8888

#define err_msg(msg,result) \
        if (result==-1) \
        {               \
            perror(msg); \
            exit(EXIT_FAILURE);\
        }

typedef struct Data{
    int socket_fd;
    char **board;
}data_t;

sem_t sem;
mouse_event_t mouse_data;


void *recv_buf(void *arg){

    data_t data = *(data_t *)arg;
    int client_fd = data.socket_fd;
    char **board = data.board;

    char buf[1024];
    while(1){
        memset(buf, 0, sizeof(buf));
        int len = read(client_fd, buf, sizeof(buf));
        if (len == 0)
        {
            printf("client close\n");
            close(client_fd);
            exit(EXIT_FAILURE);
        }
        int row=0, col=0, flag=1;
        

        for (int i = 0; i < len; i++)
        {   
            if (buf[i]=='\n')
            {
                break;
            }
            
            if( buf[i]==','){
                flag=0;
                continue;
            }
            if (flag)
            {
                row=row*10+(buf[i]-'0');
            }
            else{
                col=col*10+(buf[i]-'0');
            }
        }
        printf("row:%d col:%d\n",row,col);
        Draw_Board(board, row, col,2);
        if(Judge_wins(board, row, col, 2)){
            printf("玩家2获胜\n");
            printf_Board(board);
            exit(EXIT_FAILURE);
        }
        printf_Board(board);
        
    }
}

void *listen_event(void *arg){
    listen_mouse((mouse_event_t *)arg);
}

void *send_buf(void *arg){
    
    data_t data = *(data_t *)arg;
    int client_fd = data.socket_fd;
    char **board = data.board;
    char buf[1024];
    int game=1;

    printf("请点击1,1坐标\n");
    printf_Board(board);
    sem_wait(&sem);
    
    printf("请点击15,15坐标\n");
    printf_Board(board);

    sem_wait(&sem);
    float block_distance_row=-(mouse_data.borad_size_y/14.0), block_distance_col=mouse_data.borad_size_x/14.0;


    while(1){
        if (game)
        {
            printf("游戏开始，你是黑子，请选择你的落子位置\n");
            game=0;
            printf_Board(board);
        }
        
        sem_wait(&sem);
        memset(buf, 0, sizeof(buf));
        //判断鼠标点击的坐标是否在棋盘内
        int row; int col;
        if(mouse_data.x<=-10 && mouse_data.x>=(mouse_data.borad_size_x+10)||mouse_data.y>=10||mouse_data.y<=(mouse_data.borad_size_y-10)){
            printf("点击坐标超出棋盘范围\n");
        }else{

            //先求出可能有效的坐标
            row=round((mouse_data.y)/block_distance_row);
            col=round(mouse_data.x/block_distance_col);

            //倒回去判断这个可能的坐标是否符合误差+-10
            if ((row*block_distance_row-10)<= mouse_data.y && mouse_data.y<=(row*block_distance_row+10) && (col*block_distance_col-10)<= mouse_data.x && mouse_data.x<=(col*block_distance_col+10))
            {
                
                //判断坐标是否合规
                if(row<=0&&row>=-14&&col>=0&&col<=14){
                    sprintf(buf, "%d,%d\n", -(row-1), col+1);
                    write(client_fd, buf, strlen(buf));
                    printf("buf:%s\n",buf);
                    Draw_Board(board, -(row-1), col+1,1);
                    if(Judge_wins(board, -(row-1), col+1, 1)){
                        printf("玩家1获胜\n");
                        printf_Board(board);
                        exit(EXIT_FAILURE);
                    }
                }else{
                    printf("点击坐标超出棋盘范围\n");
                }
            }else{
                printf("点击坐标超出棋盘范围\n");
            }
            
        }

        printf_Board(board);
    }
}


int main(int argc, char *argv[]) {
    int socket_fd= socket(PF_INET, SOCK_STREAM, 0);
    err_msg("socket error",socket_fd);

    int temp_result;

    //初始化信号量
    sem_init(&sem, 0, 0);

    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr(socket_IP);
    server_addr.sin_port = htons(socket_PORT);

    temp_result=bind(socket_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
    err_msg("bind error",temp_result);

    temp_result=listen(socket_fd, 5);
    err_msg("listen error",temp_result);

    struct sockaddr_in client_addr;
    socklen_t client_addr_size = sizeof(client_addr);
    int client_fd = accept(socket_fd, (struct sockaddr *)&client_addr, &client_addr_size);
    err_msg("accept error",client_fd);

    printf("client ip: %s\n", inet_ntoa(client_addr.sin_addr));

    char **board = Board_Init();
    data_t data={client_fd, board};

    //打印棋盘
    printf("请依次点击坐标1,1和15,15开始游戏\n");
    printf_Board(board);


    //创建线程
    pthread_t read_tid, write_tid;
    pthread_create(&read_tid, NULL, recv_buf, (void *)&data);
    pthread_create(&write_tid, NULL, send_buf, (void *)&data);
    
    //开启鼠标监听线程
    pthread_t mouse_tid;

    mouse_data.sem=&sem;

    pthread_create(&mouse_tid, NULL, listen_event, (void *)&mouse_data);

    pthread_join(read_tid, NULL);
    pthread_join(write_tid, NULL);
    pthread_join(mouse_tid, NULL);
    
    
    close(client_fd);


    
    
    
    
}
